package util;

import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import entity.*;

import java.io.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Pattern;

public class NginxAnalysisUtil {
    public static final SimpleDateFormat FORMAT = new SimpleDateFormat(
            "d/MMM/yyyy:HH:mm:ss", Locale.ENGLISH);
    public static final SimpleDateFormat dateformat1 = new SimpleDateFormat(
            "yyyyMMddHHmmss");

    /**
     * 解析英文时间字符串
     *
     * @param string
     * @return
     * @throws ParseException
     */
    private static Date parseDateFormat(String string) {
        Date parse = null;
        try {
            parse = FORMAT.parse(string);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return parse;
    }

    /**
     * 解析日志的行记录
     *
     * @param line
     * @return 数组含有5个元素，分别是ip、时间、url、状态、流量
     */
    public static String[] parse(String line) {
        String ip = parseIP(line);
        String time = parseTime(line);
        String url = parseURL(line);
        String status = parseStatus(line);
        String traffic = parseTraffic(line);

        return new String[] { ip, time, url, status, traffic };
    }

    private static String parseTraffic(String line) {
        final String trim = line.substring(line.lastIndexOf("\"") + 1)
                .trim();
        String traffic = trim.split(" ")[1];
        return traffic;
    }

    private static String parseStatus(String line) {
        final String trim = line.substring(line.lastIndexOf("\"") + 1)
                .trim();
        String status = trim.split(" ")[0];
        return status;
    }

    private static String parseURL(String line) {
        final int first = line.indexOf("\"");
        final int last = line.lastIndexOf("\"");
        String url = line.substring(first + 1, last);
        return url;
    }

    private static String parseTime(String line) {
        final int first = line.indexOf("[");
        final int last = line.indexOf("+0800]");
        String time = line.substring(first + 1, last).trim();
        Date date = parseDateFormat(time);
        return dateformat1.format(date);
    }

    private static Date parseTimeAsDate(String line) {
        final int first = line.indexOf("[");
        final int last = line.indexOf("+0800]");
        String time = line.substring(first + 1, last).trim();
        return parseDateFormat(time);
    }

    private static String parseIP(String line) {
        String ip = line.split("- -")[0].trim();
        return ip;
    }

    public static JsonObject NginxLogAnalysis() {
        JsonObject data = new JsonObject();
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(new File(
                    System.getProperty("user.dir") + "\\logs", "nginx-access.log"
            ))));
            List<NginxParseTime> requestTime = new ArrayList<>();
            List<NginxParseIP> requestIp = new ArrayList<>();
            List<NginxParseDevice> requestDevice = new ArrayList<>();
            for(int i = 0; i < 24; i++) requestTime.add(new NginxParseTime(i));

            String line = null;
            while ((line = br.readLine()) != null) {
                try {
                    requestTime.get(parseTimeAsDate(line).getHours()).addCount();

                    boolean has = false;
                    String ip = parseIP(line);
                    for(NginxParseIP i : requestIp) {
                        if(i.getIp().equals(ip)) {
                            i.addCount();
                            has = true;
                            break;
                        }
                    }
                    if(!has) {
                        NginxParseIP i = new NginxParseIP(ip);
                        i.addCount();
                        requestIp.add(i);
                    }

                    has = false;
                    String device = parseDevice(line);
                    for(NginxParseDevice d : requestDevice) {
                        if(d.getDevice().equals(device)) {
                            d.addCount();
                            has = true;
                            break;
                        }
                    }
                    if(!has) {
                        NginxParseDevice d = new NginxParseDevice(device);
                        d.addCount();
                        requestDevice.add(d);
                    }
                } catch (Exception e) {
                }
            }

            data.add("requestTime", new Gson().toJsonTree(requestTime));

            requestIp.sort(Comparator.comparing(NginxParseIP::getCount).reversed());
            List<NginxParseIP> _requestIp;
            if(requestIp.size() > 20) {
                _requestIp = requestIp.subList(0, 20);
                NginxParseIP others = new NginxParseIP("Others");
                for(int i = 20; i < requestIp.size(); i++) others.setCount(others.getCount() + requestIp.get(i).getCount());
                _requestIp.add(others);
            } else {
                _requestIp = requestIp;
            }
            data.add("requestIp", new Gson().toJsonTree(_requestIp));

            data.add("requestDevice", new Gson().toJsonTree(requestDevice));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return data;
    }

    public static String parseDevice(String line) {
        boolean isWindowsPhone = line.indexOf("Windows Phone") > -1;
        boolean isSymbian = line.indexOf("SymbianOS") > -1 || isWindowsPhone;
        boolean isAndroid = line.indexOf("Android") > -1;
        boolean isFireFox = line.indexOf("Firefox") > -1;
        boolean isTablet =
                line.indexOf("iPad") > -1 ||
                line.indexOf("PlayBook") > -1 ||
                (isAndroid && line.indexOf("Mobile") == -1) ||
                (isFireFox && line.indexOf("Tablet") > -1);
        boolean isPhone = line.indexOf("iPhone") > -1 && !isTablet;
        boolean isPc = !isPhone && !isAndroid && !isSymbian;
        return isPc ? "PC" : isPhone ? "iPhone" : isAndroid ? "Android" : isTablet ? "Tablet" : "Unknown";
    }
}
